package com.momo.service.sysSetting;

import com.momo.common.common.JSONResult;
import com.momo.common.req.sysSetting.dept.SaveDeptReq;
import com.momo.common.req.sysmain.RedisUser;
import com.momo.common.util.DateUtil;
import com.momo.common.util.LevelUtil;
import com.momo.common.util.StrUtil;
import com.momo.mapper.dao.DeptDAO;
import com.momo.mapper.dataobject.DeptDO;
import com.momo.mapper.mapper.sysSetting.DeptMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * Created by MOMO on 2019/3/8.
 */
@Service
@Slf4j
public class SysDeptServiceImpl implements SysDeptService {

    @Autowired
    private DeptMapper deptMapper;

    @Override
    public JSONResult save(SaveDeptReq param, RedisUser redisUser) {
        if (checkExist(param.getSysDeptParentId(), param.getSysDeptName(), null)) {
            return JSONResult.errorMap("同一层级下存在相同名称的部门");
        }
        DeptDO deptDO = new DeptDO();
        BeanUtils.copyProperties(param, deptDO);
        String level = LevelUtil.calculateLevel(getLevel(param.getSysDeptParentId()), param.getSysDeptParentId());
        deptDO.setSysDeptLevel(level);
        if ("0".equals(param.getSysIsLeaf())) {
            //是否是叶子节点 0 是   1不是
            deptDO.setSysIsLeaf("0");
        } else {
            deptDO.setSysIsLeaf("1");
        }
        deptDO.setCreateBy(redisUser.getSysUserName());
        deptDO.setUpdateBy(redisUser.getSysUserName());
        deptDO.setCreateTime(DateUtil.getDateTime());
        deptDO.setUpdateTime(DateUtil.getDateTime());
        deptDO.setSysDeptUuid(StrUtil.genUUID());
        deptMapper.insertSelective(deptDO);
        modifyFatherLeaf(param);
        return JSONResult.ok("新增部门成功");
    }

    @Override
    public JSONResult update(SaveDeptReq param, RedisUser redisUser) {

        DeptDO before = deptMapper.getDeptByUUID(param.getSysDeptUuid());
        if (before == null) {
            return JSONResult.errorMap("待更新的部门不存在");
        }
        if (param.getSysDeptParentId().equals(before.getId())) {
            return JSONResult.errorMap("上级部门不可以是自己");
        }

        if (checkExist(param.getSysDeptParentId(), param.getSysDeptName(), before.getId())) {
            return JSONResult.errorMap("同一层级下存在相同名称的部门");
        }
        DeptDO after = new DeptDO();
        BeanUtils.copyProperties(param, after);
        after.setId(before.getId());
        String level = LevelUtil.calculateLevel(getLevel(param.getSysDeptParentId()), param.getSysDeptParentId());
        after.setSysDeptLevel(level);
        /*//更新的部门所在的层级没有发生变化，不需要更新子部门
        if (before.getSysDeptParentId().equals(param.getSysDeptParentId())){
            deptMapper.updateByPrimaryKeySelective(after);
            return JSONResult.errorMap("更新部门成功");
        }*/
        updateWithChild(before, after, param, redisUser);
        return JSONResult.ok("更新部门成功");
    }

    @Override
    public JSONResult detail(SaveDeptReq param) {
        DeptDO deptDO = deptMapper.getDeptByUUID(param.getSysDeptUuid());
        if (null == deptDO) {
            return JSONResult.errorMap("待查询的部门不存在");
        }
        return JSONResult.ok(deptDO);
    }

    @Transactional
    private void updateWithChild(DeptDO before, DeptDO after, SaveDeptReq param, RedisUser redisUser) {
        String newLevelPrefix = after.getSysDeptLevel();
        String oldLevelPrefix = before.getSysDeptLevel();
        if (!after.getSysDeptLevel().equals(before.getSysDeptLevel())) {
            //查询当前部门下的所有子部门(不包含自身)
            List<DeptDO> deptList = deptMapper.getChildDeptListByLevel(LevelUtil.calculateLevel(oldLevelPrefix, before.getId()));
            if (CollectionUtils.isNotEmpty(deptList)) {
                for (DeptDO dept : deptList) {
                    String level = dept.getSysDeptLevel();
                    if (level.indexOf(oldLevelPrefix) == 0) {
                        level = newLevelPrefix + level.substring(oldLevelPrefix.length());
                        dept.setSysDeptLevel(level);
                        dept.setSysIsLeaf(checkIsLeaf(level + ".", before.getId()));
                        dept.setUpdateTime(DateUtil.getDateTime());
                        dept.setUpdateBy(redisUser.getSysUserName());
                    }
                }
                //批量更新子部门的level
                deptMapper.batchUpdateLevel(deptList);
            }
        }
        if (!after.getSysDeptParentId().equals(before.getSysDeptParentId())) {
            DeptDO deptDO = new DeptDO();
            deptDO.setId(before.getSysDeptParentId());
            deptDO.setSysIsLeaf(checkIsLeaf(before.getSysDeptLevel() + ".", before.getId()));
            deptMapper.updateByPrimaryKeySelective(deptDO);
        }
        if ("0".equals(after.getSysIsLeaf())) {
            //是否是叶子节点 0 是   1不是
            after.setSysIsLeaf("0");
        } else {
            after.setSysIsLeaf("1");
        }
        modifyFatherLeaf(param);
        deptMapper.updateByPrimaryKeySelective(after);
    }

    //判断新增的部门是否是叶子节点以及它的父节点是否是叶子节点
    //当前新增的部门不是首级，需要更新父级节点的叶子节点
    private void modifyFatherLeaf(SaveDeptReq param) {
        //判断新增的部门是否是叶子节点以及它的父节点是否是叶子节点
        //当前新增的部门不是首级，需要更新父级节点的叶子节点
        if (!param.getSysDeptParentId().equals(0L)) {
            //更新父节点 的叶子节点变为 1
            DeptDO updateDept = new DeptDO();
            updateDept.setId(param.getSysDeptParentId());
            updateDept.setSysIsLeaf("1");
            deptMapper.updateByPrimaryKeySelective(updateDept);
        }
    }

    /**
     * 新增/编辑：检测同一层级下是否有相同名称的部门
     *
     * @param parentId 父级id
     * @param deptName 部门名称
     * @param deptId   主键
     * @return
     */
    private boolean checkExist(Long parentId, String deptName, Long deptId) {
        return deptMapper.countByNameAndParentId(parentId, deptName, deptId) > 0;
    }

    /**
     * 是否是叶子节点 0 是   1不是
     *
     * @param deptLevel
     * @return
     */
    private String checkIsLeaf(String deptLevel, Long needUpdateId) {
        return deptMapper.isLeaf(deptLevel, needUpdateId) > 0 ? "1" : "0";
    }

    private String getLevel(Long deptId) {
        DeptDO dept = deptMapper.selectByPrimaryKey(deptId);
        if (dept == null) {
            return null;
        }
        return dept.getSysDeptLevel();
    }
}
